#include "TowerControl.h"
#include "../utils/Logger.h"
#include "FlightController.h"
#include "TowerControlController.h"

TowerControl::TowerControl(unsigned int runwaysSize,
		unsigned int cantidadControllers)  {
	this->runwayCount = runwaysSize;
	this->cantidadControllers = cantidadControllers;

	this->log = Logger::instancia();
}

int TowerControl::startNewController(int controllerId) {
	pid_t pid;

	switch (pid = fork()) {
	case -1:
		return -1;
	case 0: {
		log << "TowerControl::startNewController - Creo nuevo flight controler:"<<controllerId << eol;

		FlightController fligthC(controllerId,runwayCount);
		fligthC.run();
		log << "TowerControl::startNewController - Flight controler creado y corriendo:"<<controllerId << eol;

		return 0;
	}
	default: {
		log << "TowerControl::startNewController - Agrego el controller id a la lista pid : " << pid << eol;
		this->flightControllersIds.push_back(pid);
		return pid;
	}
	}
}

int TowerControl::run() {
	pid_t pid;
	int status;

	log << "TowerControl::run - Corriendo la torre de control pid:"<< getpid()  << eol;

	switch (pid = fork()) {
	case -1:
		return -1;
	case 0: {

		for (unsigned int i = 0; i < this->cantidadControllers; i++){
			log << "TowerControl::run - Creo controlador numero:" << i << eol;
			if (startNewController(i) == 0){
				return 0;
			}
		}

		log << "TowerControl::run - Esperando que los controllers procesen los pedidos" << eol;
		waitAllFlightControllers();

		log << "TowerControl::run - Finalizando operacion de padre" << eol;

		return status;
	}
	default: {
		log << "TowerControl::run - poniendo en marcha la lectura de mensajeria para un towerControl hijo - pid :" << pid << eol;

		TowerControlController towerControlController(this->cantidadControllers,this->runwayCount);
		status = towerControlController.run();
		log << "TowerControl::run - corriendo controller para el controlador - pid :" << pid << eol;


		waitpid(pid, &status, 0);

		log << "TowerControl::run - Terminando controller para el controlador - pid :" << pid << " - status: " << status << eol;
		return status;
	}
	}
}

void TowerControl::waitAllFlightControllers() {
	int status;
	std::vector<pid_t>::iterator pids;

	for (pids = flightControllersIds.begin();pids != flightControllersIds.end(); pids++) {
		waitpid((*pids), &status, 0);
	}

	flightControllersIds.clear();
}

TowerControl::~TowerControl() {
}

